﻿--status panel 
--durability code come from Tukui

  
--get the addon namespace
local addon, ns = ...
  
--get the config values
local LabelUI = ns.LabelUI
local cfg = ns.cfg

local noshow = LabelUI.noshow
local Kill = LabelUI.Kill
local point = LabelUI.point
local InitConfigFrame = LabelUI.InitConfigFrame
local AddChatFunc = LabelUI.AddChatFunc
local textureBackground
local texturehilite
local statusbar
local classcolor
local playerclass
local iconsize
local barsize
local SaveVars

local slidebar
local Slots = {}
local SlotsLevel = {}
local SlotsFin = {}
local scaleplay = 1

local LoadConfig = function()
	textureBackground = cfg.textureBackground
	texturehilite = cfg.texturehilite
	textureBackground2 = cfg.textureBackground2
	statusbar = cfg.statusbar
	classcolor = cfg.classcolor 
	playerclass = cfg.playerclass 
	SaveVars = LabelUI.SaveVars
	if cfg.frames.slidebar then
		iconsize = cfg.frames.slidebar.iconsize
		barsize = cfg.frames.slidebar.barsize
	end
end

local RuneCheck
if cfg.playerclass == "DEATHKNIGHT" then
	local runecd = {  -- Idea to fix come from coolline, updated to what we need.
		[GetSpellInfo(50977) or "Death Gate"] = {3, 4},
		[GetSpellInfo(43265) or "Death and Decay"] = {3, 4},
		[GetSpellInfo(42650) or "Army of the Dead"] = {3, 4},
		[GetSpellInfo(49222) or "Bone Shield"] = {3, 4},
		[GetSpellInfo(47476) or "Strangulate"] = {1, 2},
		[GetSpellInfo(51052) or "Anti-Magic Zone"] = {3, 4},
		[GetSpellInfo(49184) or "Howling Blast"] = {5, 6},
		[GetSpellInfo(48982) or "Rune Tap"] = {1, 2},
	}
	RuneCheck = function(name, endtime)
		if runecd[name] then 
			for i = 1,2 do
				local start, duration, runeReady = GetRuneCooldown(runecd[name][i])
				if runeReady or ((start + duration) < endtime)then return true end
			end
		else
			return true
		end
	end
end

local function UpdateSlotFin()
	local point = -10 * (#SlotsFin - 1)
	local level = 50
	for i,cur in pairs(SlotsFin) do
		if cur.anim.scale:IsPlaying() then
			cur.level = level
		else
			cur:SetFrameLevel(level)
		end
		cur:SetFramePoint(point)
		level = level - 1	
		point = point + 10	
	end
end

local function DellSlotFin(slot)
	for i,cur in pairs(SlotsFin) do
		if cur == slot then 
			tremove(SlotsFin, i)
			break 
		end
	end
	UpdateSlotFin()
end

local function SetSlotFin(slot)
	tinsert(SlotsFin, slot)
	UpdateSlotFin()
end

local function UpdateSlotLevel()
	local level = 100
	for i,cur in pairs(SlotsLevel) do
		cur:SetFrameLevel(level)
		level = level - 1	
	end
end

local function DellSlotLevel(slot)
	for i,cur in pairs(SlotsLevel) do
		if cur == slot then 
			tremove(SlotsLevel, i)
			break 
		end
	end
	UpdateSlotLevel()
end

local function SetSlotLevel(slot)
	local insert = false
	for i,v in pairs(SlotsLevel) do
		if v.endtime > slot.endtime then
			tinsert(SlotsLevel, i, slot)
			insert = true
			break
		end						
	end
	if not insert then
		tinsert(SlotsLevel, slot)
	end
	UpdateSlotLevel()
end

local function GetFreeSlot()
	local slot = #Slots
	for i = 0, slot do
		if not Slots[i] or not Slots[i].use then
			return i
		end
	end
	return slot + 1
end

local function SetSlot(self, endtime)
	if self.slot == -1 then
		local slot = GetFreeSlot()
		if not Slots[slot] then
			Slots[slot] = CreateFrame("Frame", nil, slidebar)
			Slots[slot]:SetSize(iconsize, iconsize)
			Slots[slot].icon = Slots[slot]:CreateTexture(nil, "BORDER")
  			Slots[slot].icon:SetPoint('TOPLEFT',Slots[slot],'TOPLEFT', 2, -2)
  			Slots[slot].icon:SetPoint('BOTTOMRIGHT',Slots[slot],'BOTTOMRIGHT', -2, 2) 
  			Slots[slot].icon:SetTexCoord(0.1,0.9,0.1,0.9)
  			Slots[slot].iconBG = Slots[slot]:CreateTexture(nil, "BACKGROUND")
  			Slots[slot].iconBG:SetAllPoints(Slots[slot])
  			Slots[slot].iconBG:SetTexture(0, 0, 0, 1)
			Slots[slot]:SetAlpha(0.5)
			Slots[slot]:Hide()
			Slots[slot].anim = {}
			Slots[slot].anim.move = {} ---Slots[slot]:CreateAnimationGroup()
			local move = CreateFrame("Frame", nil, Slots[slot])
			move.duration = 1
			move.SetOffset = function(self, offsetx, offsety)
				self.stepx = offsetx / self.duration
				self.stepy = offsety / self.duration	
			end
			move.Play = function(self)
				self.start = GetTime()
				self:SetScript('OnUpdate', function(self)
					local time = GetTime() - self.start
					if not self.lasttime then
						self.lasttime = time
					end
					if time > self.duration then
						self.start = nil
						self.lasttime = nil
						self:SetScript('OnUpdate', noshow)
						return
					end
					local parent = self:GetParent()
					for i = 1, parent:GetNumPoints() do 
						local point, relativeTo, relativePoint, xOfs, yOfs = parent:GetPoint(i)
						parent:SetPoint(point, relativeTo, relativePoint, xOfs + self.stepx * (time - self.lasttime), self.stepy * (time - self.lasttime))
					end
					self.lasttime = time
				end)	
			end
			move.IsPlaying = function(self)
				if self.start then
					return true
				else
					return false
				end	
			end
			move.Stop = function(self)
				self.start = nil
				self.lasttime = nil
				self:SetScript('OnUpdate', noshow)
			end
			Slots[slot].anim.move = move
			Slots[slot].SetFramePoint = function(_, point)
				local _, _, _, xOfs = Slots[slot]:GetPoint(1)
				offset = point - xOfs
				if offset ~= 0 then
					if move:IsPlaying() then
						move:Stop()
					end
					move:SetOffset(offset, 0)
					Slots[slot].anim.move:Play()
				end
			end
			Slots[slot].anim.fade = Slots[slot]:CreateAnimationGroup()
			local alpha = Slots[slot].anim.fade:CreateAnimation("Alpha")
			alpha:SetChange(-1)
			alpha:SetSmoothing("OUT")
			alpha:SetDuration(2)
			alpha:SetOrder(1)
			Slots[slot].anim.fade:SetScript("OnFinished", function()
				Slots[slot].iconBG:SetTexture(0, 0, 0, 1)
				Slots[slot]:Hide()
				Slots[slot].use = false
			end)
			Slots[slot].anim.scale = Slots[slot]:CreateAnimationGroup()
			--Slots[slot].anim.scale:SetLooping("BOUNCE")
			local scale = Slots[slot].anim.scale:CreateAnimation("Scale")
			scale:SetScale(1.5, 1.5) 
			scale:SetDuration(0.7)
			scale:SetOrder(1)
			local scale2 = Slots[slot].anim.scale:CreateAnimation("Scale")
			scale2:SetScale(2/3, 2/3) 
			scale2:SetDuration(0.7)
			scale2:SetOrder(2)
			Slots[slot].anim.scale:SetScript("OnFinished", function()
				Slots[slot]:SetFrameLevel(Slots[slot].level)
				scaleplay = scaleplay - 1
				Slots[slot].level = 1			
			end)
		end
		Slots[slot].endtime = endtime
		SetSlotLevel(Slots[slot])
		Slots[slot].point = 0
		Slots[slot].icon:SetTexture(self.texture)
		Slots[slot].use = self
		self.slot = slot
	end
end

local function UnSetSlot(self, used)
	DellSlotFin(Slots[self.slot])
	if used then
		Slots[self.slot]:SetFrameLevel(101)
		Slots[self.slot].iconBG:SetTexture(1, 0, 0, 1)
	end
	Slots[self.slot].endtime = 0
	Slots[self.slot].anim.fade:Play()
	self.slot = -1
end

local function SetSlotPoint(self, time)
	local pointx = barsize - barsize * ( 35 / 17 / ( time + 60 )) * 34 + barsize * ( 35 / 17 / 420) * 34
	Slots[self.slot]:SetPoint("CENTER", slidebar, "LEFT", pointx, 0)
	Slots[self.slot]:Show()
end

local function SlotFinished(self)
	Slots[self.slot]:SetFrameLevel(150 + scaleplay)
	scaleplay = scaleplay + 1
	Slots[self.slot].anim.scale:Play()
	DellSlotLevel(Slots[self.slot])
	SetSlotFin(Slots[self.slot])
end

local function AddSpell(spellid, wait)
	local spell = {}
	spell.Show = SetSlot
	spell.Hide = UnSetSlot
	spell.SetTime = SetSlotPoint
	spell.Finish = SlotFinished
	spell.wait = wait
	spell.id = spellid
	spell.name, _, spell.texture = GetSpellInfo(spellid)
	spell.slot = -1
	return spell
end

local function OnUpdate(self)
	for i, spell in pairs(self.spells) do
		local start, duration, hasCooldown = GetSpellCooldown(spell.id)
		local endtime = start + duration
		if hasCooldown == 1 and start > 0 and duration > 2.5 and (not RuneCheck or RuneCheck(spell.name, endtime)) then
			if spell.timetowait then
				spell.timetowait = false	
				spell:Hide(true)			
			end
			if spell.slot == -1 then
				spell:Show(endtime)
			end
			local loctime = endtime - GetTime()
			if not spell.lastTime then spell.lastTime = loctime + 1 end
			if (spell.lastTime - loctime > 0.025) or (spell.lastTime < loctime) then
				spell:SetTime(loctime)
				spell.lastTime = loctime
			end
		elseif spell.slot ~= -1 then
			if not spell.timetowait then
				spell:Finish()
				spell.timetowait = GetTime() + spell.wait
			end
			if GetTime() > spell.timetowait then
				spell.timetowait = false
				spell:Hide()
			end
		end	
	end
end

local function CreateBar()
	if not slidebar and iconsize then
		slidebar = CreateFrame("Statusbar", "LUI_SlideBar", UIParent)
		slidebar:SetPoint(cfg.frames.slidebar.pos.a1,point(cfg.frames.slidebar.pos.af),cfg.frames.slidebar.pos.a2, cfg.frames.slidebar.pos.x, cfg.frames.slidebar.pos.y)
		--slidebar:SetPoint("CENTER", UIParent, "CENTER", 0, 0)
		slidebar:SetHeight(20)
		slidebar:SetWidth(barsize)
		slidebar:SetFrameStrata("BACKGROUND")
		slidebar:SetStatusBarTexture(statusbar)
		slidebar:SetStatusBarColor(classcolor.r, classcolor.g, classcolor.b, 0.5)
		slidebar:SetMinMaxValues(0, 1)
		slidebar:SetValue(1)
		local points = {0, 5, 15, 30, 60, 120, 360}
		slidebar.ch = {}
		--local a = 1000 / (360 ^ (0.01398))
		for i,v in pairs(points) do
			slidebar.ch[v] = {}
			slidebar.ch[v].mark = slidebar:CreateTexture(nil, "BORDER")
			slidebar.ch[v].mark:SetPoint("BOTTOM", slidebar, "BOTTOM", 0, 0)
			slidebar.ch[v].mark:SetPoint("TOP", slidebar, "TOP", 0, 0)
			slidebar.ch[v].mark:SetPoint("LEFT", slidebar, "LEFT", barsize - floor(barsize * ( 35 / 17 / ( v + 60 )) * 34) + floor(barsize * ( 35 / 17 / 420) * 34) , 0)
			slidebar.ch[v].mark:SetWidth(2)
			slidebar.ch[v].mark:SetTexture(statusbar)
			slidebar.ch[v].mark:SetVertexColor(classcolor.r, classcolor.g, classcolor.b, 0)
			slidebar.ch[v].text = slidebar:CreateFontString(nil, 'OVERLAY') 
			slidebar.ch[v].text:SetFont(cfg.font, 13)
			slidebar.ch[v].text:SetShadowOffset(1,-1)
			slidebar.ch[v].text:SetJustifyH('RIGHT')
			if v == 0 then
				slidebar.ch[v].text:SetPoint('LEFT', slidebar.ch[v].mark,'LEFT', 0, 0)
			elseif v == 360 then
				slidebar.ch[v].text:SetPoint('RIGHT', slidebar.ch[v].mark,'RIGHT', 0, 0)
			else
				slidebar.ch[v].text:SetPoint('CENTER', slidebar.ch[v].mark,'CENTER', 0, 0)
			end
			local text
			if v < 60 then
				text = v
			else
				text = (v / 60).."m"
			end
			slidebar.ch[v].text:SetText(text)
		end
		slidebar.spells = {}
		for id, wait in pairs(cfg.frames.slidebar.spells) do
			tinsert(slidebar.spells, AddSpell(id, wait))
		end
		slidebar:SetScript('OnUpdate', OnUpdate)
	elseif iconsize then
		slidebar:Show()	
	end
end

local function CreateConfigChanger()
	local curent
	local all = {
		[1] = "enable",
		[2] = "disable",	
	}
	if SaveVars:Get("slidebar|show", false) then
		curent = all[1]
	else
		curent = all[2]
	end
	local elementtable = {
		[1] = {
			type = "label",
			point = { a1 = "TOPRIGHT", a2 = "BOTTOM", af = "self.title", x = 0, y = 0 }, 
			point2 = { a1 = "TOPLEFT", a2 = "BOTTOMLEFT", af = "self.title", x = 0, y = 0 }, 	
			height = 60,
			font = "Interface\\AddOns\\LabelUI\\media\\Aquarion.otf",
			size = 14,
			justifyh = "LEFT",
			text = "SlideBar:",
			name = "slidebar",
		},
		[2] = {
			type = "dropdown",
			point = { a1 = "LEFT", a2 = "RIGHT", af = "self.named['slidebar']", x = 0, y = 0 }, 
			point2 = { a1 = "RIGHT", a2 = "RIGHT", af = "self.title", x = 0, y = 0 }, 	
			all = all,
			curent = curent,
			font = "Interface\\AddOns\\LabelUI\\media\\Aquarion.otf",
			size = 13,
			name = "slidebardropdown",
		},
	}
	local func = function(self)
	  	if self.named['slidebardropdown'].text:GetText() ~= curent then
	  	 	if self.named['slidebardropdown'].text:GetText() == all[1] then
				SaveVars:Set("slidebar|show", true)	
				CreateBar()
			else
				SaveVars:Set("slidebar|show", false)
				if slidebar then
					slidebar:Hide()
				end 	
			end
      	end	
	end
	InitConfigFrame(elementtable, 250, 250, func)
end

local function Init()
	LoadConfig()
	if SaveVars:Get("slidebar|show", false) then
		CreateBar()
	end
	AddChatFunc("SlideBar", CreateConfigChanger)
end

LabelUI:AddInit(Init, "SlideBar")

